package com.xiaoyu.lanling.activity.base;

import android.app.Activity;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.util.Log;
import android.view.MotionEvent;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate;

import com.imuxuan.floatingview.FloatingView;
import com.xiaoyu.base.BaseConstants;
import com.xiaoyu.base.app.App;
import com.xiaoyu.base.app.AppEngine;
import com.xiaoyu.lanling.BuildConfig;
import com.xiaoyu.lanling.base.push.PushAgent;
import com.xiaoyu.lanling.feature.push.PushData;

import in.srain.cube.app.lifecycle.IComponentContainer;
import in.srain.cube.app.lifecycle.LifeCycleComponent;
import in.srain.cube.app.lifecycle.LifeCycleComponentManager;
import in.srain.cube.util.CLog;
import in.srain.cube.util.UTUtil;
import in.srain.cube.util.log.LogEvent;

/**
 * Manager the components when move from a lifetime to another.
 *
 * @author Leo
 */
public abstract class BaseAppCompatActivity extends AppCompatActivity implements IComponentContainer {

    public static boolean DEBUG = BuildConfig.DEBUG;

    static {
        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
    }

    private final LifeCycleComponentManager componentContainer = new LifeCycleComponentManager();
    private final CPActivityLifecycleCallbacks lifecycleCallbacks = new CPActivityLifecycleCallbacks();
    private int mStartTime = 0;
    private int mResumeTime = 0;

    @Override
    protected void onRestart() {
        if (DEBUG) {
            showStatus("onRestart");
        }
        super.onRestart();
        componentContainer.onBecomesVisibleFromTotallyInvisible();
    }

    @Override
    protected void onPause() {
        if (DEBUG) {
            showStatus("onPause");
        }

        super.onPause();
        componentContainer.onBecomesPartiallyInvisible();
        lifecycleCallbacks.onActivityPause(this);
    }

    @Override
    protected void onResume() {
        if (DEBUG) {
            showStatus("onResume");
        }

        super.onResume();
        componentContainer.onBecomesVisibleFromPartiallyInvisible();
        lifecycleCallbacks.onActivityResume(this);

        mResumeTime++;
        final boolean isFirstTimeResume = mResumeTime == 1;
        if (AppEngine.getInstance().hasFinishedInitialJob()) {
            doOnResumeAfterAppFinishInit(isFirstTimeResume);
        } else {
            AppEngine.getInstance().addFinishInitialJobCallback(new Runnable() {
                @Override
                public void run() {
                    doOnResumeAfterAppFinishInit(isFirstTimeResume);
                }
            });
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        if (DEBUG) {
            showStatus("onCreate");
        }
        if (isSetRequestedOrientationPortrait()) {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        }

        super.onCreate(savedInstanceState);

        if (AppEngine.getInstance().hasFinishedInitialJob()) {
            doOnCreateAfterAppFinishInit(savedInstanceState);
        } else {
            AppEngine.getInstance().addFinishInitialJobCallback(new Runnable() {
                @Override
                public void run() {
                    doOnCreateAfterAppFinishInit(savedInstanceState);
                }
            });
        }
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        if (DEBUG) {
            showStatus("onRestoreInstanceState");
        }
    }

    @Override
    protected void onStart() {
        if (DEBUG) {
            showStatus("onStart");
        }

        super.onStart();

        mStartTime++;
        final boolean isFirstTimeStart = mStartTime == 1;
        if (AppEngine.getInstance().hasFinishedInitialJob()) {
            doOnStartAfterAppFinishInit(isFirstTimeStart);
        } else {
            AppEngine.getInstance().addFinishInitialJobCallback(new Runnable() {
                @Override
                public void run() {
                    doOnStartAfterAppFinishInit(isFirstTimeStart);
                }
            });
        }
    }

    private void doOnCreateAfterAppFinishInit(Bundle savedInstanceState) {
        if (DEBUG) {
            showStatus("onCreateSafelyAfterAppFinishInit");
        }
        lifecycleCallbacks.onCreateAfterAppFinishInit(this);

        onCreateSafelyAfterAppFinishInit(savedInstanceState);
    }

    private void doOnStartAfterAppFinishInit(boolean isFirstTimeStart) {
        if (DEBUG) {
            showStatus("onStartSafelyAfterAppFinishInit");
        }

        lifecycleCallbacks.onStartSafelyAfterAppFinishInit(this);
        onStartSafelyAfterAppFinishInit(isFirstTimeStart);
    }

    private void doOnResumeAfterAppFinishInit(boolean isFirstTimeResume) {
        if (DEBUG) {
            showStatus("onResumeSafelyAfterAppFinishInit");
        }
        lifecycleCallbacks.onResumeAfterAppFinishInit(this);

        onResumeSafelyAfterAppFinishInit(isFirstTimeResume);
    }

    protected void onCreateSafelyAfterAppFinishInit(@Nullable Bundle savedInstanceState) {
    }

    protected void onStartSafelyAfterAppFinishInit(boolean isFirstTimeStart) {
    }

    protected void onResumeSafelyAfterAppFinishInit(boolean isFirstTimeResume) {
    }

    @Override
    protected void onStop() {
        if (DEBUG) {
            showStatus("onStop");
        }

        super.onStop();
        componentContainer.onBecomesTotallyInvisible();
        lifecycleCallbacks.onActivityStop(this);
    }

    @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        if (DEBUG) {
            showStatus("onSaveInstanceState");
        }
        super.onSaveInstanceState(outState);
    }

    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState, PersistableBundle persistentState) {
        if (DEBUG) {
            showStatus("onRestoreInstanceState");
        }
        super.onRestoreInstanceState(savedInstanceState, persistentState);
    }

    @Override
    protected void onDestroy() {
        if (DEBUG) {
            showStatus("onDestroy");
        }
        super.onDestroy();
        componentContainer.onDestroy();
    }

    @Override
    public void addComponent(LifeCycleComponent component) {
        componentContainer.addComponent(component);
    }

    protected void showStatus(String status) {
        final String[] className = ((Object) this).getClass().getName().split("\\.");
        Log.d("cp-lifecycle", String.format("%s %s %s", className[className.length - 1], status, this));
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (DEBUG) {
            showStatus("onActivityResult");
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        return super.dispatchTouchEvent(event);
    }

    protected boolean isSetRequestedOrientationPortrait() {
        return true;
    }

    private static class CPActivityLifecycleCallbacks {

        private void onActivityResume(Activity activity) {
            App.getInstance().onActivityResume(activity);

            final LogEvent logEvent = new LogEvent("lifecycle");
            logEvent.putData("page", activity.getClass().getSimpleName());

            logEvent.startTimeForKey("ut");
            UTUtil.getInstance().onResume(activity);
            logEvent.endTimeForKey("ut");

            logEvent.startTimeForKey("upgrade");
            // TODO @sanshi (Upgrade strategy)
            // UpgradeData.Companion.getInstance().tryToCheckLatestVersion();
            logEvent.endTimeForKey("upgrade");
            CLog.i(BaseConstants.LOG_TAG_PERFORMANCE, "onActivityResume: %s", logEvent);
        }

        private void onCreateAfterAppFinishInit(Activity activity) {
            PushAgent.getInstance().onCreate(activity);
        }

        private void onResumeAfterAppFinishInit(Activity activity) {
            PushAgent.getInstance().onResume(activity);
            PushData.getInstance().tryToSyncPushToken(false);
        }

        private void onActivityPause(Activity activity) {
            final LogEvent logEvent = new LogEvent("lifecycle");
            logEvent.putData("page", activity.getClass().getSimpleName());

            logEvent.startTimeForKey("ut");
            UTUtil.getInstance().onPause(activity);
            logEvent.endTimeForKey("ut");

            CLog.i(BaseConstants.LOG_TAG_PERFORMANCE, "onActivityPause: %s", logEvent);
        }

        private void onActivityStop(Activity activity) {
            FloatingView.get().detach(activity);
        }

        public void onStartSafelyAfterAppFinishInit(Activity activity) {
            FloatingView.get().attach(activity);
        }
    }
}
